package com.utilities.parsers;

import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

import com.utilities.parsers.gbkFileParser.ParseEvents;
import com.utilities.parsers.gbkFileParser.ParseGBKFileParser;
import com.utilities.parsers.gbkFileParser.ParseListener;

public class gbkParser extends ParseListener {
	
	private ParseGBKFileParser fileParser = null;
	private HashMap<String,ArrayList<String>> map = 
		new HashMap<String, ArrayList<String>>();
	private HashMap<String,ArrayList<String>> map_neglected = 
		new HashMap<String, ArrayList<String>>();
	private String outpuFile = "c:/database/newGenes.txt";
	
	public static void main(String[] args) throws Exception
	{
		gbkParser parser = new gbkParser();
		parser.fileParser = new ParseGBKFileParser();
		parser.fileParser.addListener(parser);
		parser.fileParser.parse(new File("c:/database/NC_000913.gbk"));
	}

	public void handleEvent(ParseEvents event) {
		try
		{
			switch((ParseEvents.EventTypes)event.getEventType())
			{
				case docStarted : break;
				case docEnded: break;
				case sequence: 
				{
					break;
				}
				case cds: break;
				case gene:
				{
					String geneName = fileParser.getFeatureName() + " " + fileParser.getFeatureRef();
					String positionInfo = fileParser.getPositionalInfo();
					// This is to check that we are not reading a gene info with no position info
					assert(positionInfo != null);
					
					if (!positionInfo.contains("join"))
					{
						ArrayList<String> list = null;
						// if we have already read this gene before
						if (map.containsKey(geneName))
						{
							// fetch the positions list corresponding to this geneName
							list = map.get(geneName);
						}
						else
						{
							list = new ArrayList<String>();
						}
						list.add(positionInfo);
						map.put(geneName, list);
					}
					else
					{
						ArrayList<String> list = null;
						// if we have already read this gene before
						if (map_neglected.containsKey(geneName))
						{
							// fetch the positions list corresponding to this geneName
							list = map_neglected.get(geneName);
						}
						else
						{
							list = new ArrayList<String>();
						}
						list.add(positionInfo);
						map_neglected.put(geneName, list);
					}
					break;
				}
				case sequenceStart: 
					System.out.println("Gene location read. Fetching the sequences from the FASTA part");
					getGeneSequences();
					break;	
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}
		
	}

	private void getGeneSequences() throws Exception
	{
		FileWriter fw = new FileWriter(outpuFile);
		
		Set<String> set = map.keySet();
		for (String key : set)
		{
			ArrayList<String> list = map.get(key);
			for (String pos : list)
			{
				String temp = pos;
				boolean complement = false;
				if (pos.startsWith("complement("))
				{
					complement = true;
					pos = pos.substring(11,pos.length()-1);
				}
				if (pos.contains("complement"))
				{
					System.out.println("Nested complements found for " + key);
				}
				else
				{
					String params[] = pos.split("\\.\\.");
//					System.out.println("gene " + key + " pos " + pos);
					String geneSeq = fileParser.getGeneAtPosition(Long.parseLong(params[0]), Long.parseLong(params[1]));
					if (complement)
					{
						StringBuffer buffer = new StringBuffer();
						for (int i = geneSeq.length() - 1; i >= 0  ; i--)
						{
							char ntd = geneSeq.charAt(i);
							switch(ntd)
							{
							case 'a' :
							case 'A' :	buffer.append('t');
										break;
							case 'c' :
							case 'C' :  buffer.append('g');
										break;
							case 'g' :
							case 'G' :  buffer.append('c');
										break;
							case 't' :
							case 'T' :  buffer.append('a');
										break;
							}
						}
						complement = false;
						geneSeq = buffer.toString();
					}
					fw.write(String.format(">%s %s\n%s\n", key,temp,geneSeq));
//					System.out.println(key);
//					System.out.println(geneSeq);
				}
			}
		}
		fw.flush();
		fw.close();
	}
}
